
const db = require('db');
const superagent = require('superagent');
const log = require('tools/log');
const { toUpdate } = require('tools/sqlString');
const getAccessToken = require('tools/dd/getAccessToken');
const { sendMail } = require('nmailer');
const { decode } = require('js-base64');
const { formatMoney } = require('accounting');
const path = require('path');
const moment = require('moment');
const evaluate = require('tools/evaluate');

module.exports = async ctx => {
    const { connection, comply, run } = db.init();
    await comply('BEGIN'); // 开始事务
    try {
        const id = ctx.params.id;
        const company = ctx.headers["company-id"];
        const access_token = await getAccessToken(company);
        const settlement = await getSettlement(id, comply);
        const orders = await getOrder(id, comply);
        const userInfo = await getUserInfo(access_token, settlement.commercialSpecialistId);
        const totalAmount = await getTotalAmount(id, comply);

        if (settlement.isReceipt === '否') {
            await updateSettlement(settlement.id, run);
            await updateOrder(await queryEntry(settlement.id, run), comply);
        } else {
            await update(id, settlement, comply);
            await toMail(settlement, orders, userInfo, totalAmount);
        }

        await comply('COMMIT');
        ctx.status = 200;
        ctx.body = 'ok';
    } catch (error) {
        log('---------------------------------------------------')
        console.log(error);
        await comply('ROLLBACK');
        ctx.status = 500;
        ctx.body = error
    }
    connection.end();
}

// 更新结算单状态
async function update(id, settlement, comply) {
    await comply(`
        UPDATE settlement SET ${toUpdate({ settlementState: '待开票' })}
        WHERE id = ${id}
    `);
}

/** 获取结算单 */
async function getSettlement(id, comply) {
    return (await comply(`
        SELECT s.*
        FROM settlement AS s
        WHERE id = ${id}
    `))[0];
}

/** 获取订单数据 */
async function getOrder(id, comply) {
    return await comply(`
        SELECT o.*, s.unsettlementAmount, c.clientName
        FROM settlementEntry as s
        LEFT JOIN orders AS o ON s.ordersId = o.id
        LEFT JOIN client AS c ON c.id = o.clientId
        WHERE s.settlementId = ${id}
    `)
}

/** 获取结算总金额 */
async function getTotalAmount(id, comply) {
    const data = await comply(`
        SELECT sum(s.unsettlementAmount) as total
        FROM settlementEntry as s
        LEFT JOIN orders AS o ON s.ordersId = o.id
        WHERE s.settlementId = ${id}
    `)
    return data[0].total
}

/** 发送邮件 */
async function toMail(settlement, orders, userInfo, totalAmount) {
    if (!userInfo.email) {
        throw { status: 504, err: { sqlMessage: '邮件发送失败，请联系管理员设置企业邮箱' } }
    }

    const attachmentsPath = path.join(__dirname, '../../../../../../files', decode(settlement.settlementDetails));
    const attachmentsFilename = attachmentsPath.split('\\').pop();
    await sendMail({
        to: `高娥<gaoe@firemonkeysoft.com>`,
        cc: `李川<lichuan@firemonkeysoft.com>,Yellen<yellen@firemonkeysoft.com>,${userInfo.name}<${userInfo.email}>`,
        subject: `【开票申请】【${orders[0].clientName}】【${[...new Set(orders.map(e => e.project))].join('、')}】金额：${formatMoney(totalAmount, '')}元`,
        html: `
        <p>亲爱的财务：</p>
        <p>以下是开票的明细内容，详情请查阅, 按照要求开票</p>
        <p><b>申请人:</b> ${settlement.commercialSpecialistName}</p>
        <p><b>申请时间:</b> ${moment(settlement.createTime).format('YYYY年MM月DD日')}</p>
        <p><b>开票金额:</b> ${formatMoney(totalAmount, '')}元</p>
        <table border="1" cellspacing="0" cellpadding="5">
            <tr>
                <td>单号</td>
                <td>开票公司</td>
                <td>开票项目</td>
                <td>结算金额</td>
                <td>所属公司</td>
                <td>所属部门</td>
            </tr>
            ${orders.map(e => {
            return `
                <tr>
                    <td>${e.orderNo}</td>
                    <td>${e.clientName}</td>
                    <td>${e.project}</td>
                    <td style="text-align: right;">${formatMoney(e.unsettlementAmount, '')}¥</td>
                    <td>${companyStringMap[e.company]}</td>
                    <td>${e.deptName}</td>
                </tr>`
        })}
        </table>
        <br/>
        <p style="white-space: pre-wrap"><b>${settlement.invoicingInformation}</b></p>
        <br/>
        <p><b>备注：</b></p>
        <p style="white-space: pre-wrap">${settlement.remark}</p>
        `,
        attachments: [
            {
                filename: attachmentsFilename,
                path: attachmentsPath,
            },
        ]
    })
}

/** 获取用户数据 */
function getUserInfo(access_token, userid) {
    return new Promise((resolve, reject) => {
        superagent.post('https://oapi.dingtalk.com/topapi/v2/user/get')
            .query({ access_token })
            .send({ userid })
            .end((error, res) => {
                try {
                    if (error) throw error;
                    if (res.body.errcode !== 0) throw res.body
                    resolve(res.body.result);
                } catch (error) {
                    reject({ status: 504, error, sqlMessage: '没有找到员工数据,请切换公司' })
                    // reject({ status: 504, err: error })
                }
            })
    })
}

// 不结算的操作
// -----------------------------------------------------------------------------------------
/** 更新结算单 */
async function updateSettlement(id, run) {
    const sql = `
        UPDATE settlement SET ${toUpdate({ settlementState: '已回款' })}
        WHERE id = ${id}
    `;

    const result = await run(sql);
    if (result.err) {
        throw result.err
    }
}

/** 更新订单 */
async function updateOrder(order, comply) {
    for (let i = 0; i < order.length; i++) {
        const ot = order[i];
        const list = await comply(`
            SELECT settlementEntry.unsettlementAmount
            FROM settlementEntry, settlement
            WHERE 
                settlementEntry.ordersId = ${ot.id} 
                and settlementEntry.settlementId = settlement.id
                and settlement.settlementState = '已回款'
        `)

        let sum = 0;
        list.forEach(e => {
            sum += e.unsettlementAmount
        });

        if (sum === evaluate(`${ot.businessDay}*${ot.price}`)) {
            await comply(`
                UPDATE orders 
                SET ${toUpdate({ orderStatus: '完结' })}
                WHERE id=${ot.id}
            `)
        }
    }
}

/** 查询订单 */
async function queryEntry(id, run) {
    const sqlStr = `
    SELECT o.* 
    FROM settlementEntry as s
    LEFT JOIN orders AS o ON s.ordersId = o.id
    WHERE s.settlementId = ${id}
    `

    const result = await run(sqlStr);
    if (result.err) {
        throw result.err
    }

    return result.rows;
}

const companyStringMap = {
    'hh': '火猴',
    'ydw': '悦逗蛙',
}